package com.huantai.common.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;

/**
 * 数字的工具类.
 * 
 * @author Ma Chao
 * @version 2018年6月8日 上午9:06:06
 */
public final class NumberUtil {
    /** 不允许使用对象来调用工具类的方法 */
    private NumberUtil() {}

    /** 默认double类型的允许误差范围 */
    private static final double DEFAULT_DOUBLE_EPSILON = 0.00001d;

    /**
     * 两个 double是否相等，因为double的精度问题, 允许两个double在0.00001内的误差为相等。
     */
    public static boolean equalsWithin(double d1, double d2) {
        return Math.abs(d1 - d2) < DEFAULT_DOUBLE_EPSILON;
    }

    /**
     * 两个 double是否相等，因为double的精度问题, 允许两个double在epsilon内的误差为相等
     */
    public static boolean equalsWithin(double d1, double d2, double epsilon) {
        return Math.abs(d1 - d2) < epsilon;
    }

    /**
     * int转byte[]
     */
    public static byte[] toBytes(int v) {
        return Ints.toByteArray(v);
    }

    /**
     * long转byte[]
     */
    public static byte[] toBytes(long v) {
        return Longs.toByteArray(v);
    }

    /**
     * double转byte[]，copy from ElasticSearch Numbers
     */
    public static byte[] toBytes(double v) {
        return toBytes(Double.doubleToRawLongBits(v));
    }

    /**
     * byte[]转int
     */
    public static int toInt(byte[] bytes) {
        return Ints.fromByteArray(bytes);
    }

    /**
     * byte[]转long
     */
    public static long toLong(byte[] bytes) {
        return Longs.fromByteArray(bytes);
    }

    /**
     * byte[]转double，copy from ElasticSearch Numbers
     */
    public static double toDouble(byte[] bytes) {
        return Double.longBitsToDouble(toLong(bytes));
    }

    /**
     * 判断字符串是否合法数字
     */
    public static boolean isNumber(String str) {
        return NumberUtils.isCreatable(str);
    }

    /**
     * 判断字符串是否16进制
     */
    public static boolean isHexNumber(String value) {
        if (StringUtils.isEmpty(value)) {
            return false;
        }
        int index = value.startsWith("-") ? 1 : 0;
        return value.startsWith("0x", index) || value.startsWith("0X", index)
                || value.startsWith("#", index);
    }

    /**
     * 将10进制的String转化为int.
     * 
     * 当str为空或非数字字符串时抛NumberFormatException
     */
    public static int toInt(String str) {
        return Integer.parseInt(str);
    }

    /**
     * 将10进制的String安全的转化为int.
     * 
     * 当str为空或非数字字符串时，返回default值.
     */
    public static int toInt(String str, int defaultValue) {
        return NumberUtils.toInt(str, defaultValue);
    }

    /**
     * 将10进制的String安全的转化为long.
     * 
     * 当str或非数字字符串时抛NumberFormatException
     */
    public static long toLong(String str) {
        return Long.parseLong(str);
    }

    /**
     * 将10进制的String安全的转化为long.
     * 
     * 当str为空或非数字字符串时，返回default值
     */
    public static long toLong(String str, long defaultValue) {
        return NumberUtils.toLong(str, defaultValue);
    }

    /**
     * 将10进制的String安全的转化为double.
     * 
     * 当str为空或非数字字符串时抛NumberFormatException
     */
    public static double toDouble(String str) {
        // 统一行为，不要有时候抛NPE，有时候抛NumberFormatException
        if (str == null) {
            throw new NumberFormatException("null");
        }
        return Double.parseDouble(str);
    }

    /**
     * 将10进制的String安全的转化为double.
     * 
     * 当str为空或非数字字符串时，返回default值
     */
    public static double toDouble(String str, double defaultValue) {
        return NumberUtils.toDouble(str, defaultValue);
    }

    /**
     * 将10进制的String安全的转化为Integer.
     * 
     * 当str为空或非数字字符串时抛NumberFormatException
     */
    public static Integer toIntObject(String str) {
        return Integer.valueOf(str);
    }

    /**
     * 将10进制的String安全的转化为Integer.
     * 
     * 当str为空或非数字字符串时，返回default值
     */
    public static Integer toIntObject(String str, Integer defaultValue) {
        if (StringUtils.isEmpty(str)) {
            return defaultValue;
        }
        try {
            return Integer.valueOf(str);
        } catch (final NumberFormatException nfe) {
            return defaultValue;
        }
    }

    /**
     * 将10进制的String安全的转化为Long.
     * 
     * 当str为空或非数字字符串时抛NumberFormatException
     */
    public static Long toLongObject(String str) {
        return Long.valueOf(str);
    }

    /**
     * 将10进制的String安全的转化为Long.
     * 
     * 当str为空或非数字字符串时，返回default值
     */
    public static Long toLongObject(String str, Long defaultValue) {
        if (StringUtils.isEmpty(str)) {
            return defaultValue;
        }
        try {
            return Long.valueOf(str);
        } catch (final NumberFormatException nfe) {
            return defaultValue;
        }
    }

    /**
     * 将10进制的String安全的转化为Double.
     * 
     * 当str为空或非数字字符串时抛NumberFormatException
     */
    public static Double toDoubleObject(String str) {
        // 统一行为，不要有时候抛NPE，有时候抛NumberFormatException
        if (str == null) {
            throw new NumberFormatException("null");
        }
        return Double.valueOf(str);
    }

    /**
     * 将10进制的String安全的转化为Long.
     * 
     * 当str为空或非数字字符串时，返回default值
     */
    public static Double toDoubleObject(String str, Double defaultValue) {
        if (StringUtils.isEmpty(str)) {
            return defaultValue;
        }
        try {
            return Double.valueOf(str);
        } catch (final NumberFormatException nfe) {
            return defaultValue;
        }
    }

    /**
     * 将16进制的String转化为Integer.
     * 
     * 当str为空或非数字字符串时抛NumberFormatException
     */
    public static Integer hexToIntObject(String str) {
        // 统一行为，不要有时候抛NPE，有时候抛NumberFormatException
        if (str == null) {
            throw new NumberFormatException("null");
        }
        return Integer.decode(str);
    }

    /**
     * 将16进制的String转化为Integer，出错时返回默认值.
     */
    public static Integer hexToIntObject(String str, Integer defaultValue) {
        if (StringUtils.isEmpty(str)) {
            return defaultValue;
        }
        try {
            return Integer.decode(str);
        } catch (final NumberFormatException nfe) {
            return defaultValue;
        }
    }

    /**
     * 将16进制的String转化为Long
     * 
     * 当str为空或非数字字符串时抛NumberFormatException
     */
    public static Long hexToLongObject(String str) {
        // 统一行为，不要有时候抛NPE，有时候抛NumberFormatException
        if (str == null) {
            throw new NumberFormatException("null");
        }
        return Long.decode(str);
    }

    /**
     * 将16进制的String转化为Long，出错时返回默认值.
     */
    public static Long hexToLongObject(String str, Long defaultValue) {
        if (StringUtils.isEmpty(str)) {
            return defaultValue;
        }
        try {
            return Long.decode(str);
        } catch (final NumberFormatException nfe) {
            return defaultValue;
        }
    }
}
